package com.module.imageloader.option

import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.view.View
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.annotation.FloatRange
import androidx.annotation.IntRange
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.target.CustomViewTarget
import com.module.imageloader.loaders.ImageDelegate

/**
 * date        ：2020/7/14
 * author      ：蒙景博
 * description ：
 */
class ImageOptions constructor(builder: Builder){

    val context: Context?
    val model: Any?
    val placeHolderResId: Int
    val placeHolderDrawable: Drawable?
    val errorHolderResId: Int
    val errorHolderDrawable: Drawable?
    val fallbackHolderResId: Int
    val fallbackHolderDrawable: Drawable?
    val thumbnail: Float
    val size: ImageSize?
    val preload: Boolean
    val quality: Int
    val compressFormat: Bitmap.CompressFormat
    val decodeFormat: DecodeFormat
    val priority: Priority
    val justFromCacheLoad: Boolean
    val skipMemoryCache: Boolean
    val diskCacheStrategy: DiskCacheStrategy
    val diskCacheKey: String?

    private var delegate: ImageDelegate? = null

    init {
        this.context = builder.context
        this.model = builder.model
        this.placeHolderResId = builder.placeHolderResId
        this.placeHolderDrawable = builder.placeHolderDrawable
        this.errorHolderResId = builder.errorHolderResId
        this.errorHolderDrawable = builder.errorHolderDrawable
        this.fallbackHolderResId = builder.fallbackHolderResId
        this.fallbackHolderDrawable = builder.fallbackHolderDrawable
        this.thumbnail = builder.thumbnail
        this.size = builder.size
        this.preload = builder.preload
        this.quality = builder.quality
        this.compressFormat = builder.compressFormat
        this.decodeFormat = builder.decodeFormat
        this.priority = builder.priority
        this.justFromCacheLoad = builder.justFromCacheLoad
        this.skipMemoryCache = builder.skipMemoryCache
        this.diskCacheStrategy = builder.diskCacheStrategy
        this.diskCacheKey = builder.diskCacheKey
        this.delegate = builder.delegate
    }

    fun into(view: ImageView) {
        delegate?.loadImage(this)?.into(view)
    }

    fun <V: View> into(callback: CustomViewTarget<V, Drawable>) = delegate?.request(this, callback)

    data class Builder(
        var context: Context? = null,
        var model: Any? = null,
        var placeHolderResId: Int = 0,
        var placeHolderDrawable: Drawable? = null,
        var errorHolderResId: Int = 0,
        var errorHolderDrawable: Drawable? = null,
        var fallbackHolderResId: Int = 0,
        var fallbackHolderDrawable: Drawable? = null,
        var thumbnail: Float = 0.0f,
        var size: ImageSize? = null,
        var preload: Boolean = false,
        var quality: Int = 90,
        var compressFormat: Bitmap.CompressFormat = Bitmap.CompressFormat.PNG,
        var decodeFormat: DecodeFormat = DecodeFormat.DEFAULT,
        var priority: Priority = Priority.HIGH,
        var justFromCacheLoad: Boolean = false,
        var skipMemoryCache: Boolean = false,
        var diskCacheStrategy: DiskCacheStrategy = DiskCacheStrategy.DATA,
        var diskCacheKey: String? = null
    ) {

        var delegate: ImageDelegate? = null

        internal fun setContext(context: Context) = apply { this.context = context }

        internal fun setImageLoader(delegate: ImageDelegate?) = apply { this.delegate = delegate }

        /**
         * 资源地址
         */
        fun load(model: Any) = apply { this.model = model }

        /**
         * 占位图
         */
        fun placeHolder(@DrawableRes resId: Int) = apply { this.placeHolderResId = resId }

        /**
         * 占位图
         */
        fun placeHolder(drawable: Drawable) = apply { this.placeHolderDrawable = drawable }

        /**
         * 错误占位符
         */
        fun errorHolder(@DrawableRes resId: Int) = apply { this.errorHolderResId = resId }

        /**
         * 错误占位符
         */
        fun errorHolder(drawable: Drawable) = apply { this.errorHolderDrawable = drawable }

        fun fallbackHolder(@DrawableRes resId: Int) = apply { this.fallbackHolderResId = resId }

        fun fallbackHolder(drawable: Drawable) = apply { this.fallbackHolderDrawable = drawable }

        fun thumbnail(@FloatRange(from = 0.0, to = 1.0) thumbnail: Float) = apply { this.thumbnail = thumbnail }

        fun override(width: Int, height: Int) = override(ImageSize(width, height))

        fun override(size: ImageSize) = apply { this.size = size }

        /**
         * 是否启用预加载
         */
        fun preload(enable: Boolean) = apply { this.preload = enable }

        /**
         * 设置加载的图片质量
         */
        fun quality(@IntRange(from = 1, to = 100) quality: Int) = apply { this.quality = quality }

        /**
         * 设置图片编码格式，png或者jpg
         */
        fun compressFormat(format: Bitmap.CompressFormat) = apply { this.compressFormat = format }

        /**
         * 设置图片的解码格式， default，PREFER_RGB_565， PREFER_ARGB_8888
         */
        fun decodeFormat(format: DecodeFormat) = apply { this.decodeFormat = format }

        /**
         * 设置加载代理优先级
         */
        fun priority(priority: Priority) = apply { this.priority = priority }

        /**
         * 设置仅从缓存加载
         */
        fun justFromCacheLoad(justFromCacheLoad: Boolean) = apply { this.justFromCacheLoad = justFromCacheLoad }

        /**
         * 是否跳过内存缓存
         */
        fun skipMemoryCache(skipMemoryCache: Boolean) = apply { this.skipMemoryCache = skipMemoryCache }

        /**
         * 设置缓存模式
         */
        fun diskCacheStrategy(diskCacheStrategy: DiskCacheStrategy) = apply { this.diskCacheStrategy = diskCacheStrategy }

        /**
         * 设置缓存key
         */
        fun diskCacheKey(key: String) = apply { this.diskCacheKey = key }

        fun build(): ImageOptions = ImageOptions(this)
    }
}